package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.nacos.api.config.filter.IFilterConfig;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.injector.methods.DeleteById;
import com.baomidou.mybatisplus.core.injector.methods.UpdateById;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.exception.CustException;
import com.heima.model.common.constants.NewsAutoScanConstants;
import com.heima.model.common.constants.WmNewsMessageConstants;
import com.heima.model.common.constants.WmUserMaterialConstants;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.*;
import com.heima.model.wemedia.vos.WmNewsVo;
import com.heima.utils.threadlocal.WmThreadLocalUtils;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmMaterialService;
import com.heima.wemedia.service.WmNewsService;
import com.sun.xml.bind.v2.model.core.ID;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.Internal;
import org.aspectj.weaver.ast.Var;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import springfox.documentation.spring.web.json.Json;

import javax.naming.NamingEnumeration;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Value("${file.oss.web-site}")
    String webSite;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    WmMaterialService wmMaterialService;

    @Autowired
    private WmUserMapper wmUserMapper;

    /**
     * 自媒体文章人工审核
     *
     * @param status 2  审核失败  4 审核成功
     * @param dto
     * @return
     */
    @Override
    public ResponseResult updateStatus(Short status, NewsAuthDto dto) {
        if (dto == null || dto.getId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2.查询文章
        WmNews wmNews = getById(dto.getId());
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "查詢不到這篇文章");
        }
        //3.修改文章状态
        wmNews.setStatus(status);
        if (StringUtils.isNotBlank(dto.getMsg())) {
            wmNews.setReason(dto.getMsg());
        }
        updateById(wmNews);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 查询文章详情
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult findWmNewsVo(Integer id) {
        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews news = getById(id);
        if (news == null || news.getUserId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章或者文章作者未查询到");
        }
        WmUser wmUser = wmUserMapper.selectOne(Wrappers.<WmUser>lambdaQuery()
                .eq(WmUser::getId, news.getUserId()));
        if (wmUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章作者未查询到");
        }
        WmNewsVo wmNewsVo = new WmNewsVo();
        BeanUtils.copyProperties(news, wmNewsVo);
        wmNewsVo.setAuthorName(wmUser.getName());
        ResponseResult result = ResponseResult.okResult(wmNewsVo);
        result.setHost(webSite);
        return result;
    }

    /**
     * 查询文章列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findList(NewsAuthDto dto) {
        dto.checkParam();
        Integer page = dto.getPage();
        if (StringUtils.isNotBlank(dto.getTitle())) {
            dto.setTitle("%" + dto.getTitle() + "%");
        }
        dto.setPage((page - 1) * dto.getSize());
        List<WmNewsVo> listAndPage = baseMapper.findListAndPage(dto);

        int listCount = baseMapper.findListCount(dto);
        ResponseResult result = new PageResponseResult(page, dto.getSize(), listCount, listAndPage);
        result.setHost(webSite);
        return result;
    }

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Override
    @Transactional
    public ResponseResult submitNews(WmNewsDto dto) {
        //1.参数校验
        if (dto == null || StringUtils.isBlank(dto.getTitle()) || StringUtils.isBlank(dto.getTitle())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //保存或修改文章
        WmNews wmNews = new WmNews();
        String image = null;
        if (dto.getImages() != null) {
            List<String> images = dto.getImages();
            //数组去Oss头部后再拼接成a.jpg,b.jpg格式
            image = imageListToString(images);
            if (StringUtils.isNotBlank(image)) {
                wmNews.setImages(image);
            }
        }
        BeanUtils.copyProperties(dto, wmNews);
        //如果选择自动图片布局的话,数据库的type设置为null
        if (dto.getType() == -1) {
            wmNews.setType(null);
        }
        wmNews.setUserId(WmThreadLocalUtils.getUser().getId());
        if (wmNews.getCreatedTime() == null) {
            wmNews.setCreatedTime(new Date());
        }
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable((short) 1);  //类型为上架
        // 该功能为保存、修改（是否有id）、保存草稿的共用方法
        if (wmNews.getId() != null) {  //有Id的话证明上次有保存
            //如果有id修改文章，先删除所有素材关联关系
            wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery()
                    .eq(WmNewsMaterial::getNewsId, wmNews.getId()));
        }
        //3.关联文章和素材关系表    两个关系表image的url的问题待解决  //这个地方不用判空
        List<Map> content = JSON.parseArray(dto.getContent(), Map.class);
        //抽取文章中image的url    这个地方有可能为空
        List<String> imageList = parseContentImage(content);
        //遍历这个"内容为图片url集合,与news_martial对比得到id \
        List<Integer> urlIdList = null;
        if (imageList != null) {
            urlIdList = parseIdbyImageUrl(imageList);
        }
        //切割images并放入对应集合中
        List<String> collect = null;

        //自动情况下是从内容里面取图片
        if (dto.getType() == -1) {
            if (urlIdList != null && urlIdList.size() > 2) {
                //三图    urlIdList集合不为空的话imageList必不为空
                collect = imageList.stream().limit(3).collect(Collectors.toList());
                String s = imageListToString(collect);
                wmNews.setImages(s);
                wmNews.setType((short) 3);
            } else if (urlIdList != null && 0 < urlIdList.size() && urlIdList.size() < 2) {
                //一图
                collect = imageList.stream().limit(1).collect(Collectors.toList());
                String s = imageListToString(collect);
                wmNews.setImages(s);
                wmNews.setType((short) 1);
            } else {
                //无图
                wmNews.setType((short) 0);
            }
            //提交为草稿的时候直接返回   不去修改关系图中的数据
            if (dto.getStatus() == 0) {
                return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
            }
            //自动选择封面且为提交状态  修改封面与素材的关系图
            if (collect != null || dto.getStatus() == 1) {
                List<Integer> list = parseIdbyImageUrl(collect);
                wmNewsMaterialMapper.saveRelations(list, dto.getId(), WmUserMaterialConstants.COVER_QUOTE);
            }
        }

        //如果不是自动提交选择图片数据的话
        if (urlIdList != null && urlIdList.size() > 0 && dto.getStatus() == 1) {
            //关联内容中的图片与素材的关系  0是内容引用,1是封面引用
            wmNewsMaterialMapper.saveRelations(urlIdList, dto.getId(), WmUserMaterialConstants.CONTENT_QUOTE);
        }
        if (dto.getStatus() == 1 && dto.getType() != -1) {
            //非自动提交
            String s = imageListToString(dto.getImages());
            List<Integer> integers = paseStringToList(s);
            wmNewsMaterialMapper.saveRelations(integers, dto.getId(), WmUserMaterialConstants.COVER_QUOTE);
        }
        //保存或者修改文章信息
        saveOrUpdate(wmNews);

        // 4 发消息给admin审核文章   消息的生產方
        Map map = new HashMap();
        map.put("wmNewsId", wmNews.getId());
        kafkaTemplate.send(NewsAutoScanConstants.WM_NEWS_AUTO_SCAN_TOPIC, JSON.toJSONString(map));

        //5.死信队列完成定时审核功能
        if (dto.getPublishTime().getTime() > new Date().getTime()) {
            long time = dto.getPublishTime().getTime() - new Date().getTime();
            MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    //消息持久化
//                    message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                    //设置消息过期时间  字符串格式
                    message.getMessageProperties().setExpiration(String.valueOf(time));
                    System.out.println("发出消息的时间是"+time);
                    return message;
                }
            };
            //发送消息
            Integer id = wmNews.getId();
            rabbitTemplate.convertAndSend("later_exchange", "later_key", id, messagePostProcessor);
        }


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    private List<Integer> paseStringToList(String image) {
        //只有一條数据的时候
        List<Integer> idList = new ArrayList<>();
        if (!image.contains(",")) {
            WmMaterial one = wmMaterialService.getOne(Wrappers.<WmMaterial>lambdaQuery()
                    .eq(WmMaterial::getUrl, image)
                    .eq(WmMaterial::getUserId, WmThreadLocalUtils.getUser().getId()));
            idList.add(one.getId());
            if (one == null) {
                //沒有查詢到本條數據的話   素材被删除了
                CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
        } else {
            String[] split = image.split(",");
            for (String s : split) {
                WmMaterial one = wmMaterialService.getOne(Wrappers.<WmMaterial>lambdaQuery()
                        .eq(WmMaterial::getUrl, s)
                        .eq(WmMaterial::getUserId, WmThreadLocalUtils.getUser().getId()));
                idList.add(one.getId());
            }
            //图片存到草稿中有可能被删除   通过判断前端传递来的image数组长度和遍历获取到的id长度来判断数据是否被删除
            if (idList == null || idList.size() == 0 || idList.size() < split.length) {
                //素材被删除完了
                CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
        }
        return idList;
    }

    /**
     * 根据url获取对应的materialid
     *
     * @param imageList 存放这个url的集合
     * @return 存放对应id的集合
     */
    private List<Integer> parseIdbyImageUrl(List<String> imageList) {
        List<Integer> wmMaterialIdList = new ArrayList<>();
        for (String s : imageList) {
            //根据素材url获取图片
            WmMaterial one = wmMaterialService.getOne(Wrappers.<WmMaterial>lambdaQuery()
                    .eq(WmMaterial::getUrl, s)
                    .eq(WmMaterial::getUserId, WmThreadLocalUtils.getUser().getId()));
            if (one == null) {
                CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            wmMaterialIdList.add(one.getId());
        }
        return wmMaterialIdList;
    }

    /**
     * 根据文章内容获取相应的url集合
     *
     * @param content 文章内容
     * @return 文章内包含的所有的url集合
     */
    private List<String> parseContentImage(List<Map> content) {
        //一个List<String>类型的集合接收这个url集合
        List<String> contentUrlList = new ArrayList<>();
        for (Map map : content) {
            if (map.get("type").equals("image")) {
                String value = (String) map.get("value");
                String url = value.replace(webSite, "")
                        .replace(" ", "");
                contentUrlList.add(url);
            }
        }
        //返回一个包含内容所有图片的url集合
        return contentUrlList;
    }

    /**
     * 把image转换为,拼接的格式
     *
     * @param images
     * @return
     */
    private String imageListToString(List<String> images) {
        if (images.size() > 0) {
            return images.toString().replace(webSite, "")
                    .replace(" ", "")
                    .replace("[", "")
                    .replace("]", "");
        }
        return null;
    }

    /**
     * 根据文章id查询文章
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult findWmNewsById(Integer id) {
        //根据id查询当前文章hA
        if (id == null) {
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews one = getOne(Wrappers.<WmNews>lambdaQuery()
                .eq(WmNews::getId, id));
        if (one == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        ResponseResult result = ResponseResult.okResult(one);
        result.setHost(webSite);
        return result;
    }

    @Override
    public ResponseResult delNews(Integer id) {

        if (id == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews one = getOne(Wrappers.<WmNews>lambdaQuery()
                .eq(WmNews::getId, id));
        if (one == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //判断当前文章的状态,如果已经发布并且已经上架的话不能够删除
        if (one.getStatus() == 9 && one.getEnable() == 1) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_ENABLE_DELETE);
        }
        //根据当前文章来删除相关的关联表
        wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery()
                .eq(WmNewsMaterial::getNewsId, id));
        removeById(one);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    //上架或者下架
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        if (dto == null || dto.getId() == null) {
            CustException.cust(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews one = getOne(Wrappers.<WmNews>lambdaQuery()
                .eq(WmNews::getId, dto.getId()));
        if (one == null) {
            CustException.cust(AppHttpCodeEnum.NEWS_NOT_EXIT);
        }
        if (one.getStatus().equals(9)) {
            CustException.cust(AppHttpCodeEnum.NEWS_NOT_ISSUE);
        }
        one.setEnable(dto.getEnable());
        updateById(one);

        //通过kafka消息队列把东西发过来
        if (one.getArticleId() != null) {
            Map<String, Object> map = new HashMap<>();
            map.put("enable", dto.getEnable());
            map.put("articleId", one.getArticleId());
            kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(map));
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 查询所有自媒体文章
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findAll(WmNewsPageReqDto dto) {
        //1.参数校验;还是分页查询需要能够检查分页参数
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        dto.checkParam();
        //2.执行逻辑
        LambdaQueryWrapper<WmNews> warpper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(dto.getKeyword())) {
            //关键字不为空的话,就把关键字作为查询条件
            warpper.like(WmNews::getTitle, dto.getKeyword());
        }
        if (dto.getStatus() != null) {
            //如果查询状态不为空,把状态作为查询条件
            warpper.eq(WmNews::getStatus, dto.getStatus());
        }
        if (dto.getBeginPubDate() != null && dto.getEndPubDate() != null) {
            //按时间进行查询
            warpper.between(WmNews::getCreatedTime, dto.getBeginPubDate(), dto.getEndPubDate());
        }
        if (dto.getChannelId() != null) {
            warpper.eq(WmNews::getChannelId, dto.getChannelId());
        }
        Integer wmUserId = WmThreadLocalUtils.getUser().getId();
        if (wmUserId == null) {
            //非法访问,报需要访问权限错误
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        warpper.eq(WmNews::getUserId, wmUserId);
        //根据时间进行一个倒序排序
        warpper.orderByDesc(WmNews::getCreatedTime);
        IPage<WmNews> pageParame = new Page<>(dto.getPage(), dto.getSize());
        IPage<WmNews> page = page(pageParame, warpper);
        //3.参数返回
        //封装参数并且返回  图片地址
        //前端参数为host遍历拼接
//        List<WmNews> list = new ArrayList<>();
//        for (WmNews record : records) {
//            record.setImages(webSite + record.getImages());
//            list.add(record);
//        }
        ResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal(), page.getRecords());
        result.setHost(webSite);
        return result;
    }

    /**
     * 查询需要发布的文章id列表
     *
     * @return
     */
    @Override
    public List<Integer> findRelease() {
        //查询状态为4或为8的数据且发布时间小于当前时间
        List<WmNews> list = list(Wrappers.<WmNews>lambdaQuery()
                .lt(WmNews::getPublishTime, new Date())
                .in(WmNews::getStatus, 4, 8)
                .select(WmNews::getId));
        List<Integer> collect = list.stream().map(x -> x.getId()).collect(Collectors.toList());
        return collect;

    }

}